package com.java.example.app

import android.bluetooth.BluetoothGatt
import android.media.MediaPlayer
import android.os.Handler
import android.os.Message
import android.text.TextUtils
import android.util.Log
import com.blankj.utilcode.util.SPUtils
import com.blankj.utilcode.util.ToastUtils
import com.clj.fastble.BleManager
import com.clj.fastble.callback.BleGattCallback
import com.clj.fastble.callback.BleIndicateCallback
import com.clj.fastble.callback.BleNotifyCallback
import com.clj.fastble.callback.BleReadCallback
import com.clj.fastble.callback.BleWriteCallback
import com.clj.fastble.data.BleDevice
import com.clj.fastble.exception.BleException
import com.java.example.R
import com.java.example.app.Latte.applicationContext
import com.java.example.app.MyApplication.Companion.sInstance
import com.java.example.ui.activity.MainActivity
import com.java.example.ui.dialog.BleDisconnectDialog
import com.java.example.util.SpeakUtils


/**
 * Created by chenll on 2024/8/22 0022.
 */
class BleDeviceManager private constructor() {
    private var mBleDevice: BleDevice? = null

    private var mBleConnectListener: BleConnectionListener? = null

    private var mBleReadListener: BleReadListener? = null

    private var mBleIndicateListener: BleIndicateListener? = null

    private var mBleGattCallback: BleGattCallback? = null

    private var mBleReadCallback: BleReadCallback? = null

    private var mBleIndicateCallback: BleIndicateCallback? = null

    private var bleNotifyCallback: BleNotifyCallback? = null

    private var mBleWriteCallback: BleWriteCallback? = null

    private var bleDisconnectDialog: BleDisconnectDialog? = null
    /**是否连接状态 */ //private boolean isConnected;
    /**
     * 上一次连接成功的时间
     */
    private var lastConnectTime: Long = 0

    /**
     * 上一次连接成功的mac地址
     */
    private var lastConnectMac: String? = null

    /**
     * 是否是持续连接状态
     */
    private val isKeepConnecting = false

    fun setBleDevice(bleDevice: BleDevice?) {
        mBleDevice = bleDevice
    }

    private object BleDeviceManagerHolder {
        val instance: BleDeviceManager = BleDeviceManager()
    }

    private val mHandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when (msg.what) {
                KEEP_CONNECT -> {}
                KEEP_CONNECTING -> {
                    val bleDevice = msg.obj as BleDevice
                    BleManager.getInstance().connect(bleDevice.mac, mBleGattCallback)
                }
            }
        }
    }

    /**
     * 开始轮训，保持长链接
     *
     * @param bleDevice
     */
    private fun startPoll(bleDevice: BleDevice) {
        /*if(!isConnected){
            return;
        }
        Message msg=mHandler.obtainMessage();
        msg.what=KEEP_CONNECT;
        msg.obj=bleDevice;
        mHandler.sendMessageDelayed(msg,1000*10);*/
    }

    /**
     * 开始直连
     *
     * @param bleDevice
     */
    private fun startToConnect(bleDevice: BleDevice) {
        if (isLogout) {
            return
        }
        //        Log.i("AAAA","startToConnect");
        val msg = mHandler.obtainMessage()
        msg.obj = bleDevice
        msg.what = KEEP_CONNECTING
        mHandler.sendMessage(msg)
    }

    private fun init() {
        BleManager.getInstance().init(sInstance)
        mBleGattCallback = object : BleGattCallback() {
            override fun onStartConnect() {
                if (mBleConnectListener != null) {
                    mBleConnectListener!!.onStartConnect()
                }
            }

            override fun onConnectFail(bleDevice: BleDevice, exception: BleException) {
                Log.i("AAAA", "连接失败")
                SPUtils.getInstance().put(Constant.IS_CONNECT_BLUE, false)
                if (isLogout) {
                    return
                }
                if (mBleConnectListener != null) {
                    mBleConnectListener!!.onConnectFail(bleDevice, exception)
                }
                if (!BleManager.getInstance().isBlueEnable) {
                    doRealDisconnect()
                } else {
                    if (TextUtils.isEmpty(lastConnectMac)) {
                        //如果没有上一次连接的mac地址，表示这是第一次连接失败，不需要重连
                        //nothing
                    } else {
                        val currentTime = System.currentTimeMillis()
                        if ((currentTime - lastConnectTime) < 20 * 60 * 1000) {
                            //发送指令
                            startToConnect(bleDevice)
                        } else {
                            //nothing
                        }
                    }
                }
            }

            override fun onConnectSuccess(bleDevice: BleDevice, gatt: BluetoothGatt, status: Int) {
                isLogout = false
                //isConnected=true;
                lastConnectTime = 0
                lastConnectMac = null
                if (bleDisconnectDialog != null) {
                    bleDisconnectDialog!!.dismiss()
                }
                setBleDevice(bleDevice)
                ToastUtils.showLong("蓝牙连接成功")
                SPUtils.getInstance().put(Constant.IS_CONNECT_BLUE, true)
                //                startPoll(bleDevice);
                if (mBleConnectListener != null) {
                    mBleConnectListener!!.onConnectSuccess(bleDevice, gatt, status)
                }
                SpeakUtils.speak("蓝牙连接成功")
//                val mediaPlayer = MediaPlayer.create(applicationContext, R.raw.ble_connected)
//                mediaPlayer.start() // 无需调用preare()方法，create()方法中已调用
            }

            override fun onDisConnected(isActiveDisConnected: Boolean, device: BleDevice, gatt: BluetoothGatt, status: Int) {
                //断开，分为2中情况，
                //第一种，主动断开，就是关闭蓝牙
                //第二种，卷尺长时间不动，断开
                //断开时，先判断蓝牙是否可以用，如果不能用吗，直接走断开逻辑
                //如果可以用，尝试自动连接，
                //先判断当前处于什么状态，如果是自动重连状态，先判断当前时间与最后一次连接时间的差值，如果超过30分钟，放弃，在20分钟以内，直接发送连接指令
                //如果不是重连的状态，先记录当前最后一次连接的时间与连接的mac地址，然后发送连接指令
                if (isLogout) {
                    return
                }
                if (!BleManager.getInstance().isBlueEnable) {
                    doRealDisconnect()
                } else {
                    if (TextUtils.isEmpty(lastConnectMac)) {
                        //如果没有上一次连接的mac地址，表示这是第一次断开连接
                        lastConnectMac = device.mac
                        lastConnectTime = System.currentTimeMillis()
                        //发送指令
                        startToConnect(device)
                    } else {
                        val currentTime = System.currentTimeMillis()
                        if ((currentTime - lastConnectTime) < 20 * 60 * 1000) {
                            //发送指令
                            startToConnect(device)
                        } else {
                            doRealDisconnect()
                        }
                    }
                }
                //isConnected=false;
                val activity = Latte.configurator.getConfiguration<MainActivity>(ConfigKeys.ACTIVITY)
                if (activity == null || isLogout) {
                    return
                }
                if (bleDisconnectDialog == null) {
                    bleDisconnectDialog = BleDisconnectDialog.create()
                }
                if (activity != null && !activity.isFinishing) {
                    bleDisconnectDialog!!.showDialog(activity)
                    SPUtils.getInstance().put(Constant.IS_CONNECT_BLUE, false)
                }
                if (mBleConnectListener != null) {
                    mBleConnectListener!!.onDisConnected(isActiveDisConnected, device, gatt, status)
                }
                SpeakUtils.speak("蓝牙断开连接")
                val mediaPlayer = MediaPlayer.create(applicationContext, R.raw.ble_disconnected)
                mediaPlayer.start() // 无需调用preare()方法，create()方法中已调用
            }
        }

        mBleIndicateCallback = object : BleIndicateCallback() {
            override fun onIndicateSuccess() {
                if (mBleIndicateListener != null) {
                    mBleIndicateListener!!.onIndicateSuccess()
                }
            }

            override fun onIndicateFailure(exception: BleException) {
                if (mBleIndicateListener != null) {
                    mBleIndicateListener!!.onIndicateFailure(exception)
                }
            }

            override fun onCharacteristicChanged(data: ByteArray) {
                //Log.i("AAAA","onCharacteristicChanged:"+new String(data));
                if (mBleIndicateListener != null) {
                    mBleIndicateListener!!.onCharacteristicChanged(data)
                }
            }
        }
        mBleReadCallback = object : BleReadCallback() {
            override fun onReadSuccess(data: ByteArray) {
                if (mBleReadListener != null) {
                    mBleReadListener!!.onReadSuccess(data)
                }
            }

            override fun onReadFailure(exception: BleException) {
                if (mBleReadListener != null) {
                    mBleReadListener!!.onReadFailure(exception)
                }
            }
        }
        mBleWriteCallback = object : BleWriteCallback() {
            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray) {
            }

            override fun onWriteFailure(exception: BleException) {
            }
        }

        bleNotifyCallback = object : BleNotifyCallback() {
            override fun onNotifySuccess() {
                if (mBleIndicateListener != null) {
                    mBleIndicateListener!!.onIndicateSuccess()
                }
            }

            override fun onNotifyFailure(exception: BleException) {
                if (mBleIndicateListener != null) {
                    mBleIndicateListener!!.onIndicateFailure(exception)
                }
            }

            override fun onCharacteristicChanged(data: ByteArray) {
                if (mBleIndicateListener != null) {
                    mBleIndicateListener!!.onCharacteristicChanged(data)
                }
            }
        }
    }


    /**
     * 执行真正断开后的操作
     */
    private fun doRealDisconnect() {
        SPUtils.getInstance().put(Constant.IS_CONNECT_BLUE, false)
        clearBleDevice()
    }

    /**
     * 判断是否是由退出登录引发的断开操作
     */
    private var isLogout = false

    init {
        init()
    }

    fun disconnect() {
        isLogout = true
        SPUtils.getInstance().put(Constant.IS_CONNECT_BLUE, false)
        BleManager.getInstance().disconnectAllDevice()
    }

    val currentBleDevice: BleDevice?
        /**
         * 获取当前已经连接的蓝牙设备
         *
         * @return
         */
        get() {
            if (mBleDevice != null && BleManager.getInstance().isConnected(mBleDevice)) {
                return mBleDevice
            }
            return null
        }

    /**
     * 清除当前连接的蓝牙设备
     */
    fun clearBleDevice() {
        if (mBleDevice != null) {
            if (BleManager.getInstance().isConnected(mBleDevice)) {
                BleManager.getInstance().disconnect(mBleDevice)
            }
            mBleDevice = null
        }
    }

    /**
     * 蓝牙连接
     */
    fun connect(bleDevice: BleDevice?) {
        BleManager.getInstance().connect(bleDevice, mBleGattCallback)
    }

    fun write(bleDevice: BleDevice?, data: ByteArray?) {
        BleManager.getInstance().write(bleDevice, SERVICE_UUID, CHARACTERISTIC_UUID, data, mBleWriteCallback)
    }

    fun read(bleDevice: BleDevice?) {
        BleManager.getInstance().read(bleDevice, SERVICE_UUID, CHARACTERISTIC_UUID, mBleReadCallback)
    }

    fun indicate(bleDevice: BleDevice?) {
        BleManager.getInstance().indicate(bleDevice, SERVICE_UUID, CHARACTERISTIC_UUID, mBleIndicateCallback)
    }

    fun indicateNew(bleDevice: BleDevice?) {
//        BleManager.getInstance().indicate(bleDevice, SERVICE_UUID_NEW, CHARACTERISTIC_UUID_NEW,  bleNotifyCallback);
        BleManager.getInstance().notify(bleDevice, SERVICE_UUID_NEW, CHARACTERISTIC_UUID_NEW, bleNotifyCallback)
    }

    fun setOnBleConnectListener(listener: BleConnectionListener) {
        this.mBleConnectListener = listener
    }

    interface BleConnectionListener {
        fun onStartConnect()

        fun onConnectFail(bleDevice: BleDevice?, exception: BleException?)

        fun onConnectSuccess(bleDevice: BleDevice?, gatt: BluetoothGatt?, status: Int)

        fun onDisConnected(isActiveDisConnected: Boolean, device: BleDevice?, gatt: BluetoothGatt?, status: Int)
    }

    fun setOnBleReadListener(listener: BleReadListener?) {
        this.mBleReadListener = listener
    }

    fun setOnBleIndicateListener(listener: BleIndicateListener?) {
        this.mBleIndicateListener = listener
    }

    interface BleReadListener {
        fun onReadSuccess(data: ByteArray?)

        fun onReadFailure(exception: BleException?)
    }

    interface BleIndicateListener {
        fun onIndicateSuccess()

        fun onIndicateFailure(exception: BleException?)

        fun onCharacteristicChanged(data: ByteArray?)
    }

    interface BleWriteListener {
        fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?)

        fun onWriteFailure(exception: BleException?)
    }

    companion object {
        const val SERVICE_UUID: String = "0000fff0-0000-1000-8000-00805f9b34fb"

        const val CHARACTERISTIC_UUID: String = "0000fff4-0000-1000-8000-00805f9b34fb"

        //新接入设备UUID
        const val SERVICE_UUID_NEW: String = "0000ffb0-0000-1000-8000-00805f9b34fb"

        const val CHARACTERISTIC_UUID_NEW: String = "0000ffb2-0000-1000-8000-00805f9b34fb"

        /**
         * 保持连接
         */
        private const val KEEP_CONNECT = 201

        /**
         * 保持直连
         */
        private const val KEEP_CONNECTING = 202

        fun getInstance(): BleDeviceManager {
            return BleDeviceManagerHolder.instance
        }
    }
}
